#include "stack.h"
#include <stdio.h>
#include <stdbool.h>
#include <assert.h>
#include <malloc.h>
 
/* When the space isn't enough.
   we will increase such space.*/
int const increment = 100;
 
void initialize(stack *s, int sz)
{
    s->size = sz;
    s->quantity = 0;
    s->top = 0;
    s->storage = NULL;
}
 
void cleanUp(stack *s)
{
    if (s->storage != NULL)
        free(s->storage);
        
    s->quantity = 0;
    s->top = 0;
    s->storage = 0;
}
 
bool isFull(stack *s)
{
    if (s->quantity == 0)
        return false;
    
    return s->top >= s->quantity;
}
 
int count(stack *s)
{
    return s->top;
}
 
void inflate(stack *s, int increase)
{
    int i;
    int newQuantity = s->quantity + increase;
    unsigned char *newStorage;
    int sumByte = newQuantity * s->size;
    
    assert(increase > 0);
    
    newStorage = (unsigned char *)malloc(sumByte);
    
    assert(newStorage != NULL);
    
    for (i = 0; i < s->quantity * s->size; i++)
        newStorage[i] = s->storage[i];
        
    free(s->storage);
    s->storage = newStorage;
    s->quantity = newQuantity;
}
 
bool isEmpty(stack *s)
{
    return s->top <= 0;
}
 
void * pop(stack *s)
{
    if (s->top == 0)
        return 0;

    s->top--;
    return (void *)(s->storage + 
                    s->top * s->size);
}
 
void push(stack *s, const void *element)
{
    int i;
    int startByte = s->top * s->size;
    unsigned char *e = (unsigned char*)element;
    if (isFull(s) || s->quantity == 0)
        inflate(s, increment);
    
    for (i = 0; i < s->size; i++)
        s->storage[startByte + i] = e[i];
    
    s->top++;
}